package net.beyondts.mplug.utils;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOCase;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Project: mplug-project<br/>
 * Description: <br/>
 * Created at: 2019-1-11<br/>
 * Owned by beyondts.
 *
 * @author blazecrystal
 * @version 1.0.0
 */
public class FileUtils {

    /**
     * 列出指定目录下的文件，名称包含特定字符串（可以使用wildcard）的文件.
     *
     * @param dir {@link String} 目录
     * @param nameFilter {@link String} 名称过滤器（可以使用wildcard）
     * @param capSense boolean 大小写敏感
     * @return {@link File}[] 文件列表
     * @throws IOException IO异常
     */
    public static File[] listFiles(String dir, String nameFilter,
                                   boolean capSense) throws IOException {
        File dirx = new File(dir);
        if (dirx.exists() && dirx.isDirectory()) {
            return dirx
                    .listFiles(new SimpleFilenameFilter(nameFilter, capSense));
        } else {
            throw new IOException("\"" + dir
                    + "\" doesn't exist or isn't a directory");
        }
    }

    /**
     * 列出目录下的符合要求的文件列表。
     *
     * @param dir {@link String} 待列的目录
     * @param nameFilter {@link String} 文件名关键字
     * @param capSense boolean 是否大小写敏感，true为敏感，false为不敏感
     * @param subDirInclude boolean 是否搜索子目录
     * @return List&lt;File&gt; 符合要求的文件列表
     * @throws IOException IO异常
     */
    public static List<File> listFiles(String dir, String nameFilter,
                                       boolean capSense, boolean subDirInclude) throws IOException {
        List<File> files = new ArrayList<File>();
        if (!subDirInclude) {
            File[] tmpArray = listFiles(dir, nameFilter, capSense);
            for (File tmp : tmpArray) {
                files.add(tmp);
            }
        } else {
            File baseDir = new File(dir);
            if (baseDir.exists() && baseDir.isDirectory()) {
                File[] tmpArray = baseDir.listFiles();
                if (tmpArray != null) {
                    for (File tmp : tmpArray) {
                        if (tmp.isFile() && accept(tmp, nameFilter, capSense)) {
                            files.add(tmp);
                        } else if (tmp.isDirectory()) {
                            files.addAll(listFiles(tmp.getAbsolutePath(),
                                    nameFilter, capSense, subDirInclude));
                        }
                    }
                }
            } else {
                throw new IOException("\"" + dir
                        + "\" doesn't exist or isn't a directory");
            }
        }
        return files;
    }

    private static boolean accept(File file, String nameFilter, boolean capSense) {
        String tmpFilter = nameFilter;
        String tmpFilename = file.getName();
        IOCase iocase = IOCase.SENSITIVE;
        if (!capSense) {
            tmpFilter = tmpFilter.toLowerCase();
            tmpFilename = tmpFilename.toLowerCase();
            iocase = IOCase.INSENSITIVE;
        }
        return FilenameUtils.wildcardMatch(tmpFilename, tmpFilter, iocase);
    }

    /**
     * 列出目录下的符合要求的文件列表。
     *
     * @param dir {@link String} 待列的目录
     * @param nameFilter {@link String} 文件名关键字
     * @param capSense boolean 是否大小写敏感，true为敏感，false为不敏感
     * @param subDirInclude boolean 是否搜索子目录
     * @return List&lt;File&gt; 符合要求的文件列表
     * @throws IOException IO异常
     */
    public static List<String> listFilenames(String dir, String nameFilter,
                                             boolean capSense, boolean subDirInclude) throws IOException {
        List<String> files = new ArrayList<>();
        if (!subDirInclude) {
            File[] tmpArray = listFiles(dir, nameFilter, capSense);
            for (File tmp : tmpArray) {
                files.add(tmp.getAbsolutePath());
            }
        } else {
            File baseDir = new File(dir);
            if (baseDir.exists() && baseDir.isDirectory()) {
                File[] tmpArray = baseDir.listFiles();
                if (tmpArray != null) {
                    for (File tmp : tmpArray) {
                        if (tmp.isFile() && accept(tmp, nameFilter, capSense)) {
                            files.add(tmp.getAbsolutePath());
                        } else if (tmp.isDirectory()) {
                            files.addAll(listFilenames(tmp.getAbsolutePath(),
                                    nameFilter, capSense, subDirInclude));
                        }
                    }
                }
            } else {
                throw new IOException("\"" + dir
                        + "\" doesn't exist or isn't a directory");
            }
        }
        return files;
    }

    /**
     * delete content at the line from a file.
     * @param filepath String absolute path of the file
     * @param line int the line no to delete, start from 1
     */
    public static void deleteLine(String filepath, int line) throws IOException {
        if (line < 0) {
            return;
        }
        BufferedReader br = null;
        PrintWriter pw = null;
        final String CHARSET = "UTF-8";
        try {
            br = new BufferedReader(new InputStreamReader(new FileInputStream(filepath), CHARSET));
            List<String> content = new ArrayList<>();
            String tmp = null;
            while((tmp = br.readLine()) != null) {
                content.add(tmp);
            }
            if (content.size() < line || content.size() < 1) {
                return;
            }
            content.remove(line);
            pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(filepath), CHARSET), true);
            for (int i = 0; i < content.size(); i++) {
                pw.print(content.get(i));
                if (i < content.size() - 1) {
                    pw.println();
                }
            }
            pw.flush();
        } finally {
            IOUtils.closeQuietly(br);
            IOUtils.closeQuietly(pw);
        }
    }
}
